package net.gdface.bean;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import net.gdface.bean.BeanPropertySupport.DiffNode;
import net.gdface.bean.exception.CycleReferenceException;

import static net.gdface.bean.BeanPropertySupport.BEAN_SUPPORT;
import static net.gdface.utils.SimpleLog.log;
import static net.gdface.json.JsonSupports.jsonSupportInstance;

@FixMethodOrder(MethodSorters.NAME_ASCENDING) // 指定测试方法按定义的顺序执行
public class BeanPropertySupportTest {
	@BeforeClass
    public static void setUpBeforeClass() throws Exception {
		BeanPropertySupport.setTraceEnabled(true);
	}
    @Test
    public void test2PublicFieldBean() {
    	try {
    		log("read from public field");
    		PublicFieldBean bean = new PublicFieldBean("tom","guangzhou",23,null,null);
    		Map<String, Object> values = BEAN_SUPPORT.describe(bean);
    		log("values:{}",jsonSupportInstance().toJSONString(values, true));
    		assertTrue(null == BEAN_SUPPORT.getPropertyChecked(bean, "props.device.mode"));
    		BEAN_SUPPORT.setPropertyChecked(bean, "groupId", 77);
    		BEAN_SUPPORT.setPropertyChecked(bean, "child.historyNumer", "20.7");
    		BEAN_SUPPORT.setPropertyChecked(bean, "child.props.name", "chess");
    		BEAN_SUPPORT.setPropertyChecked(bean, "logs[0]", "2022-11-02");
    		BEAN_SUPPORT.setPropertyChecked(bean, "props.device.mode", "DEV1");
    		assertTrue(77 == bean.groupId);
    		values = BEAN_SUPPORT.describe(bean);
    		log("values:{}",jsonSupportInstance().toJSONString(values, true));
		} catch (Exception e) {
			e.printStackTrace();
			assertTrue(false);
		}
    }
    @Test
    public void test3Copy() {
    	try {
    		log("copy Bean to Bean");
    		PublicFieldBean bean1 = new PublicFieldBean("tom","guangzhou",23,null,new StandardBean());
    		PublicFieldBean bean2 = new PublicFieldBean();
    		BEAN_SUPPORT.copyProperties(bean2, bean1);
    		log("bean2:{}",JSON.toJSONString(bean2, true));
    		
    	} catch (Exception e) {
    		e.printStackTrace();
    		assertFalse(false);
    	}
    }
    @Test
    public void test4Copy() {
    	try {
    		log("copy Map to Bean");
    		ImmutableMap<String, ? extends Object> bean1 = ImmutableMap.of("name","tom","location","guangzhou","groupId",23,"createTime",new Date());
    		PublicFieldBean bean2 = new PublicFieldBean();
    		BEAN_SUPPORT.copyProperties(bean2, bean1);
    		log("bean2:{}",JSON.toJSONString(bean2, true));
    		assertTrue(23 == bean2.groupId);
    	} catch (Exception e) {
    		e.printStackTrace();
    		assertFalse(false);
    	}
    }
    @Test 
    public void test5NameResolver(){
    	NameResolver resolver = new NameResolver();
    	String name = "device.hello.location(os).time[LAST].users[name=hello]";
//    	String name = "name1.name2[index].name3(key)";
    	log("name {}",name);
    	while(resolver.hasNested(name)){
    		String next = resolver.next(name);
    		log("next:{}",next);
    		if(resolver.isMapped(next)){
    			log("property:{}",resolver.getProperty(next));
    		}else if(resolver.isIndexed(next)){
    			log("index: property {}  {}",resolver.getProperty(next),resolver.getIndex(next));
    		}else if(resolver.isSearched(next)){
    			log("index.key:{}",resolver.getIndex(next));
    		}
    		name = resolver.remove(name);
    		log("name {}",name);
    	}
    	if(resolver.isMapped(name)){
			log("property:{},key:{}",resolver.getProperty(name),resolver.getKey(name));
		}else if(resolver.isIndexed(name)){
			log("index:{} {}",resolver.getProperty(name),resolver.getIndex(name));
		}else if(resolver.isSearched(name)){
			log("index.key:P:{} {} {}",resolver.getProperty(name),resolver.getField(name),resolver.getValue(name));
		}
    }
    @Test 
    public void test6NameResolver(){
    	NameResolver resolver = new NameResolver();
//    	String name = "users";
    	String name = "device.hello.location(os).time[LAST].users[name=hello]";
//    	String name = "name1.name2[index].name3(key)";
    	log("name {}",name);
    	while(resolver.hasNested(name)){
    		String next = resolver.nextRight(name);
    		log("next:{}",next);
    		if(resolver.isMapped(next)){
    			log("property:{}",resolver.getProperty(next));
    		}else if(resolver.isIndexed(next)){
    			log("index: property {}  {}",resolver.getProperty(next),resolver.getIndex(next));
    		}else if(resolver.isSearched(next)){
    			log("index.key:P:{} {} {}",resolver.getProperty(name),resolver.getField(name),resolver.getValue(name));
    		}
    		name = resolver.removeRight(name);
    		log("name {}",name);
    	}
    	if(resolver.isMapped(name)){
    		log("property:{},key:{}",resolver.getProperty(name),resolver.getKey(name));
    	}else if(resolver.isIndexed(name)){
    		log("index:{} {}",resolver.getProperty(name),resolver.getIndex(name));
    	}else if(resolver.isSearched(name)){
    		log("index.key:P:{} {} {}",resolver.getProperty(name),resolver.getField(name),resolver.getValue(name));
    	}
    	{
    		String n2 = "user";
    		assertTrue(n2.equals(resolver.nextRight(n2)));
    	}
    }
    @Test
    public void test7JsonString(){
    	String json = "{\"modified\":0,\"initialized\":8388607,\"new\":false,\"id\":3,\"groupId\":2,\"features\":0,\"name\":\"hello5\",\"physicalAddress\":\"000000000002\",\"addressType\":\"MAC\",\"iotCard\":null,\"status\":\"ENABLE\",\"tokenTime\":0,\"screenInfo\":\"21V960x1080\",\"fixedMode\":\"FLOOR\",\"osArch\":null,\"network\":\"4G\",\"versionInfo\":null,\"model\":\"EAMDEV0\",\"vendor\":null,\"deviceDetail\":{\"device_name\":\"AN01\",\"manufacturer\":\"NXP\",\"made_date\":\"2022-01-02\"},\"props\":{\"disk_capacity\":\"1.2GB\"},\"planId\":\"3709047235ABCEDFG\",\"targetId\":\"20220825182312501665d\",\"remark\":null,\"updateTime\":\"2022-09-01 17:49:22\",\"createTime\":\"2022-08-03 12:21:38\"}";
    	PublicFieldBean bean = new PublicFieldBean("tom","guangzhou",23,null,null);
    	bean.setJsonProps(json);
    	try {
    		/** String类型JSON 字段测试 */
			assertTrue(BEAN_SUPPORT.getPropertyChecked(json, "id").equals(3));
			assertTrue(BEAN_SUPPORT.getPropertyChecked(json, "props.disk_capacity").equals("1.2GB"));
			BEAN_SUPPORT.setPropertyChecked(bean, "jsonProps.props.remark", "hello");
			assertTrue("hello".equals(BEAN_SUPPORT.getPropertyChecked(bean, "jsonProps.props.remark")));
			/** JSON字符串为输入参数测试,这种情况下要从返回值获取修改后的字符串 */
			String json2 = (String)BEAN_SUPPORT.setPropertyChecked(json, "props.remark", "hello");
			assertTrue("hello".equals(BEAN_SUPPORT.getPropertyChecked(json2, "props.remark")));
			/** JSON String字段初始为null的读写测试 */
			bean.setJsonProps(null);
			assertNull(BEAN_SUPPORT.getPropertyChecked(bean, "jsonProps.remark"));
			BEAN_SUPPORT.setPropertyChecked(bean, "jsonProps.props.remark", "hello");
			assertTrue("hello".equals(BEAN_SUPPORT.getPropertyChecked(bean, "jsonProps.props.remark")));
			/** JSON String字段初始为null的直接写入JSON对象 */
			bean.setJsonProps(null);
			JSONObject newjson=new JSONObject().fluentPut("name", "jerry").fluentPut("address", "拉萨路小学").fluentPut("updateTime", "2003-01-01 00:00:00");
			BEAN_SUPPORT.setPropertyChecked(bean, "jsonProps", newjson);
			assertTrue("jerry".equals(BEAN_SUPPORT.getPropertyChecked(bean, "jsonProps.name")));
			/** 向已经有的JSON string中更新内容 */
			String jstr="{\"targetId\":\"20220825182312501665d\",\"remark\":null,\"updateTime\":\"2022-09-01 17:49:22\",\"createTime\":\"2022-08-03 12:21:38\"}";
			BEAN_SUPPORT.setPropertyChecked(bean, "jsonProps", jstr);
			assertTrue("jerry".equals(BEAN_SUPPORT.getPropertyChecked(bean, "jsonProps.name")));
			assertTrue("2022-09-01 17:49:22".equals(BEAN_SUPPORT.getPropertyChecked(bean, "jsonProps.updateTime")));
			assertTrue("20220825182312501665d".equals(BEAN_SUPPORT.getPropertyChecked(bean, "jsonProps.targetId")));			
		} catch (Exception e) {
			e.printStackTrace();
			assertTrue(false);
		}
    }
    /**
     * 测试数组搜索表达式 [key=value]
     */
    @Test
    public void test8SearchExpress(){
    	PublicFieldBean bean = new PublicFieldBean("tom","guangzhou",23,null,null);
    	ArrayList<JSONObject> list = Lists.newArrayList(
    			new JSONObject().fluentPut("name", "jerry").fluentPut("phone", 13077988845L).fluentPut("country", "usa"),
    			new JSONObject().fluentPut("name", "sam").fluentPut("phone", 13082171823L).fluentPut("country", "uk"),
    			new JSONObject().fluentPut("name", "lang").fluentPut("phone", 15022983884L).fluentPut("country", "cn"),
    			new JSONObject().fluentPut("name", "brown").fluentPut("phone", 17700261845L).fluentPut("country", "hk")
    			);
    	bean.setLogs(list);
    	
    	try {
    		/** 在 logs 数组中搜索name字段为jerry的对象 */
			Object element = BEAN_SUPPORT.getPropertyChecked(bean, "logs[name=jerry]");
			assertNotNull(element);
			assertTrue("usa".equals(BEAN_SUPPORT.getPropertyChecked(element, "country")));
			BEAN_SUPPORT.setPropertyChecked(bean, "logs[name=jerry].phone",16887822235L);
			element = BEAN_SUPPORT.getPropertyChecked(bean, "logs[name=jerry]");
			assertTrue(Long.valueOf(16887822235L).equals(BEAN_SUPPORT.getPropertyChecked(element, "phone")));
			JSONObject tomas = new JSONObject().fluentPut("name", "tomas").fluentPut("phone", 17754984127L).fluentPut("country", "kr");
			/**  添加到列表头部测试 */
			BEAN_SUPPORT.setProperty(bean, "logs[-1]", tomas);
			assertTrue("tomas".equals(BEAN_SUPPORT.getProperty(bean, "logs[0].name")));
			/**  添加到列表尾部测试 */
			JSONObject cherry = new JSONObject().fluentPut("name", "cherry").fluentPut("phone", 10090125622L).fluentPut("country", "gm");
			BEAN_SUPPORT.setProperty(bean, "logs[+]", cherry);
			assertTrue("cherry".equals(BEAN_SUPPORT.getProperty(bean, "logs[+].name")));
			assertTrue(new Long(10090125622L).equals(BEAN_SUPPORT.getProperty(bean, "logs[+].phone")));
		} catch (Exception e) {
			e.printStackTrace();
			assertTrue(false);
		}
    }
    @Test
    public void test9Different(){
    	try {
        	String json1 = "{\"modified\":0,\"initialized\":8388607,\"new\":false,\"id\":3,\"groupId\":2,\"features\":0,\"name\":\"hello5\",\"physicalAddress\":\"000000000002\",\"addressType\":\"MAC\",\"iotCard\":null,\"status\":\"ENABLE\",\"tokenTime\":0,\"screenInfo\":\"21V960x1080\",\"fixedMode\":\"FLOOR\",\"osArch\":null,\"network\":\"4G\",\"versionInfo\":null,\"model\":\"EAMDEV0\",\"vendor\":null,\"deviceDetail\":{\"device_name\":\"AN01\",\"manufacturer\":\"NXP\",\"made_date\":\"2022-01-02\"},\"props\":{\"disk_capacity\":\"[1.2GB]\"},\"planId\":\"3709047235ABCEDFG\",\"targetId\":\"20220825182312501665d\",\"remark\":null,\"updateTime\":\"2022-09-01 17:49:22\",\"createTime\":\"2022-08-03 12:21:38\"}";
        	String json2 = "{\"modified\":0,\"initialized\":8388607,\"new\":true,\"id\":22,\"groupId\":2,\"features\":0,\"name\":\"hello5\",\"physicalAddress\":\"000000000002\",\"addressType\":\"MAC\",\"iotCard\":null,\"status\":\"ENABLE\",\"tokenTime\":0,\"screenInfo\":\"21V960x1080\",\"fixedMode\":\"FLOOR\",\"osArch\":null,\"network\":\"4G\",\"versionInfo\":null,\"model\":\"EAMDEV0\",\"vendor\":null,\"deviceDetail\":{\"device_name\":\"AN01\",\"manufacturer\":\"NXP\",\"made_date\":\"2022-01-02\"},\"props\":{\"disk_capacity\":\"[1.3GB]\"},\"planId\":\"3709047235ABCEDFG\",\"targetId\":\"20220825182312501665d\",\"remark\":null,\"updateTime\":\"2022-09-01 17:49:22\",\"createTime\":\"2022-08-03 12:21:38\"}";

    		PublicFieldBean bean1 = new PublicFieldBean("tom","guangzhou",23,new Date(),null);
    		bean1.setJsonProps(json1);
    		StandardBean standardBean = new StandardBean("070199", "北京路32号")
    				.setProps(new JSONObject().fluentPut("last_date", "1973-01-01"));
    		@SuppressWarnings("deprecation")
			PublicFieldBean bean2 = new PublicFieldBean("jerry","shanghai",7,new Date(103,1,1),standardBean);
    		bean2.setJsonProps(json2);
    		Map<String, DiffNode> diffNodes = BEAN_SUPPORT.different(bean1, bean2);
    		log("diff Nodes \n{}",jsonSupportInstance().toJSONString(diffNodes,true));
    		assertTrue(diffNodes.containsKey("child"));
		} catch (Exception e) {
			e.printStackTrace();
			assertTrue(false);
		}
    }
    @Test
    public void test10Different(){
    	try {
    		String json1 = "{\"modified\":0,\"initialized\":8388607,\"new\":false,\"id\":3,\"groupId\":2,\"features\":0,\"name\":\"hello5\",\"physicalAddress\":\"000000000002\",\"addressType\":\"MAC\",\"iotCard\":null,\"status\":\"ENABLE\",\"tokenTime\":0,\"screenInfo\":\"21V960x1080\",\"fixedMode\":\"FLOOR\",\"osArch\":null,\"network\":\"4G\",\"versionInfo\":null,\"model\":\"EAMDEV0\",\"vendor\":null,\"deviceDetail\":{\"device_name\":\"AN01\",\"manufacturer\":\"NXP\",\"made_date\":\"2022-01-02\"},\"props\":{\"disk_capacity\":\"[1.2GB]\"},\"planId\":\"3709047235ABCEDFG\",\"targetId\":\"20220825182312501665d\",\"remark\":null,\"updateTime\":\"2022-09-01 17:49:22\",\"createTime\":\"2022-08-03 12:21:38\"}";
    		String json2 = "{\"modified\":0,\"initialized\":8388607,\"new\":true,\"id\":22,\"groupId\":2,\"features\":0,\"name\":\"hello5\",\"physicalAddress\":\"000000000002\",\"addressType\":\"MAC\",\"iotCard\":null,\"status\":\"ENABLE\",\"tokenTime\":0,\"screenInfo\":\"21V960x1080\",\"fixedMode\":\"FLOOR\",\"osArch\":null,\"network\":\"4G\",\"versionInfo\":null,\"model\":\"EAMDEV0\",\"vendor\":null,\"deviceDetail\":{\"device_name\":\"AN01\",\"manufacturer\":\"NXP\",\"made_date\":\"2022-01-02\"},\"props\":{\"disk_capacity\":\"[1.3GB]\"},\"planId\":\"3709047235ABCEDFG\",\"targetId\":\"20220825182312501665d\",\"remark\":null,\"updateTime\":\"2022-09-01 17:49:22\",\"createTime\":\"2022-08-03 12:21:38\"}";
    		StandardBean standardBean = new StandardBean("070199", "北京路32号")
    				.setProps(new JSONObject().fluentPut("last_date", "1973-01-01"));
    		PublicFieldBean bean1 = new PublicFieldBean("tom","guangzhou",23,new Date(),standardBean);
    		bean1.setJsonProps(json1);
    		ArrayList<JSONObject> list = Lists.newArrayList(
    				new JSONObject().fluentPut("name", "jerry").fluentPut("phone", 13077988845L).fluentPut("country", "usa"),
    				new JSONObject().fluentPut("name", "sam").fluentPut("phone", 13082171823L).fluentPut("country", "uk"),
    				new JSONObject().fluentPut("name", "lang").fluentPut("phone", 15022983884L).fluentPut("country", "cn"),
    				new JSONObject().fluentPut("name", "brown").fluentPut("phone", 17700261845L).fluentPut("country", "hk")
    				);
    		bean1.setLogs(list);
    		@SuppressWarnings("deprecation")
    		PublicFieldBean bean2 = new PublicFieldBean("jerry","shanghai",7,new Date(103,1,1),null);
    		bean2.setJsonProps(json2);
    		Map<String, DiffNode> diffNodes = BEAN_SUPPORT.different(bean1, bean2);
    		log("diff Nodes \n{}",jsonSupportInstance().toJSONString(diffNodes,true));
    		assertTrue(diffNodes.containsKey("child"));
    	} catch (Exception e) {
    		e.printStackTrace();
    		assertTrue(false);
    	}
    }
    @Test 
	public void test11Index(){
    	PublicFieldBean bean = new PublicFieldBean("tom","guangzhou",23,null,null);
    	/**  添加到列表尾部测试 */
		JSONObject cherry = new JSONObject().fluentPut("name", "cherry").fluentPut("phone", 10090125622L).fluentPut("country", "gm");
    	BEAN_SUPPORT.setProperty(bean, "props.users[+]", cherry);
    	assertTrue("cherry".equals(BEAN_SUPPORT.getProperty(bean, "props.users[+].name")));
	}
	@Test 
	public void test12GetVisitor(){
		try {
			String json = "{\"modified\":0,\"initialized\":8388607,\"new\":false,\"id\":3,\"groupId\":2,\"features\":0,\"name\":\"hello5\",\"physicalAddress\":\"000000000002\",\"addressType\":\"MAC\",\"iotCard\":null,\"status\":\"ENABLE\",\"tokenTime\":0,\"screenInfo\":\"21V960x1080\",\"fixedMode\":\"FLOOR\",\"osArch\":null,\"network\":\"4G\",\"versionInfo\":null,\"model\":\"EAMDEV0\",\"vendor\":null,\"deviceDetail\":{\"device_name\":\"AN01\",\"manufacturer\":\"NXP\",\"made_date\":\"2022-01-02\"},\"props\":{\"disk_capacity\":\"[1.2GB]\"},\"planId\":\"3709047235ABCEDFG\",\"targetId\":\"20220825182312501665d\",\"remark\":null,\"updateTime\":\"2022-09-01 17:49:22\",\"createTime\":\"2022-08-03 12:21:38\"}";
			PublicFieldBean bean = new PublicFieldBean("tom","guangzhou",23, null, null);
			bean.setJsonProps(json);
			assertTrue("tom".equals(BEAN_SUPPORT.getPropertyChecked(bean, "name")));
			assertTrue(Integer.valueOf(23).equals(BEAN_SUPPORT.getPropertyChecked(bean, "groupId")));
			assertTrue(Integer.valueOf(8388607).equals(BEAN_SUPPORT.getPropertyChecked(bean, "jsonProps.initialized")));
			/** 多组嵌套测试 */
			assertTrue("[1.2GB]".equals(BEAN_SUPPORT.getPropertyChecked(bean, "jsonProps.props.disk_capacity")));
			/** 没找到字段返回 null测试 */
			assertNull(BEAN_SUPPORT.getPropertyChecked(bean, "jsonProps.props.yellow"));
			
		} catch (Exception e) {
			e.printStackTrace();
			assertTrue(false);
		}
	}
	@Test
	public void test13Describe(){
		{
			/** 为null的对象测试 */
			Map<String, Object> desc = BEAN_SUPPORT.describe(null);
			log("desc:{}",jsonSupportInstance().toJSONString(desc, true));
			assertTrue(1==desc.size() && desc.keySet().iterator().next().equals("."));
		}
		{
			/** 非JSON对象测试 */
			Map<String, Object> desc = BEAN_SUPPORT.describe("[hello]");
			log("desc:{}",jsonSupportInstance().toJSONString(desc, true));
			assertTrue(1==desc.size() && desc.keySet().iterator().next().equals("."));
		}
		{
			/** 复杂嵌套对象(JSON)测试 */
			String json = "{\"modified\":0,\"initialized\":8388607,\"new\":false,\"id\":3,\"groupId\":2,\"features\":0,\"name\":\"hello5\",\"physicalAddress\":\"000000000002\",\"addressType\":\"MAC\",\"iotCard\":null,\"status\":\"ENABLE\",\"tokenTime\":0,\"screenInfo\":\"21V960x1080\",\"fixedMode\":\"FLOOR\",\"osArch\":null,\"network\":\"4G\",\"versionInfo\":null,\"model\":\"EAMDEV0\",\"vendor\":null,\"deviceDetail\":{\"device_name\":\"AN01\",\"manufacturer\":\"NXP\",\"made_date\":\"2022-01-02\"},\"props\":{\"disk_capacity\":\"[1.2GB]\"},\"planId\":\"3709047235ABCEDFG\",\"targetId\":\"20220825182312501665d\",\"remark\":null,\"updateTime\":\"2022-09-01 17:49:22\",\"createTime\":\"2022-08-03 12:21:38\"}";
			PublicFieldBean bean = new PublicFieldBean("tom","guangzhou",23,null,null);
			bean.setJsonProps(json);
	    	ArrayList<JSONObject> list = Lists.newArrayList(
	    			new JSONObject().fluentPut("name", "jerry").fluentPut("phone", 13077988845L).fluentPut("country", "usa"),
	    			new JSONObject().fluentPut("name", "sam").fluentPut("phone", 13082171823L).fluentPut("country", "uk"),
	    			new JSONObject().fluentPut("name", "lang").fluentPut("phone", 15022983884L).fluentPut("country", "cn"),
	    			new JSONObject().fluentPut("name", "brown").fluentPut("phone", 17700261845L).fluentPut("country", "hk")
	    			);
	    	bean.setLogs(list);
    		Map<String, Object> desc = BEAN_SUPPORT.describe(bean);
    		log("desc:{}",jsonSupportInstance().toJSONString(desc, true));
    		assertNull(desc.get("child"));
    		assertTrue(desc.get("createTime") instanceof Date);
    		assertTrue(Integer.valueOf(23).equals(desc.get("groupId")));
    		assertTrue("guangzhou".equals(desc.get("location")));
    		assertTrue(null == desc.get("logs"));
    		assertTrue("tom".equals(desc.get("name")));
    		assertTrue("2022-08-03 12:21:38".equals(desc.get("jsonProps.createTime")));
    		assertTrue("EAMDEV0".equals(desc.get("jsonProps.model")));
    		assertTrue("EAMDEV0".equals(desc.get("jsonProps.model")));
    		assertNull(desc.get("jsonProps.osArch"));
    		assertNull(desc.get("jsonProps.remark"));
    		assertTrue(Integer.valueOf(8388607).equals(desc.get("jsonProps.initialized")));
    		assertTrue("4G".equals(desc.get("jsonProps.network")));
    		assertTrue(Integer.valueOf(3).equals(desc.get("jsonProps.id")));
    		assertTrue("21V960x1080".equals(desc.get("jsonProps.screenInfo")));
    		assertTrue("hello5".equals(desc.get("jsonProps.name")));
    		assertTrue(Integer.valueOf(0).equals(desc.get("jsonProps.features")));
    		assertTrue(Integer.valueOf(0).equals(desc.get("jsonProps.tokenTime")));
    		assertTrue("000000000002".equals(desc.get("jsonProps.physicalAddress")));
    		assertTrue("AN01".equals(desc.get("jsonProps.deviceDetail.device_name")));
    		assertTrue("NXP".equals(desc.get("jsonProps.deviceDetail.manufacturer")));
    		assertTrue("2022-01-02".equals(desc.get("jsonProps.deviceDetail.made_date")));
    		assertTrue("FLOOR".equals(desc.get("jsonProps.fixedMode")));
    		assertNull(desc.get("jsonProps.versionInfo"));
    		assertTrue("2022-09-01 17:49:22".equals(desc.get("jsonProps.updateTime")));
    		assertTrue("ENABLE".equals(desc.get("jsonProps.status")));
    		assertNull(desc.get("jsonProps.vendor"));
    		assertTrue("20220825182312501665d".equals(desc.get("jsonProps.targetId")));
    		assertTrue("MAC".equals(desc.get("jsonProps.addressType")));
    		assertTrue("3709047235ABCEDFG".equals(desc.get("jsonProps.planId")));
    		assertTrue(Integer.valueOf(0).equals(desc.get("jsonProps.modified")));
    		assertTrue(Integer.valueOf(2).equals(desc.get("jsonProps.groupId")));
    		assertTrue(Boolean.FALSE.equals(desc.get("jsonProps.new")));
    		assertNull(desc.get("jsonProps.iotCard"));
    		assertTrue("[1.2GB]".equals(desc.get("jsonProps.props.disk_capacity")));
    		assertNull(desc.get("props"));    		
		}
	}
	@Test
	public void test14CycleReference() {
		try {
			JSONObject json1 = new JSONObject().fluentPut("props", new JSONObject().fluentPut("p2", new JSONObject()));
			BEAN_SUPPORT.setProperty(json1, "props.p2.p3", json1);
			BEAN_SUPPORT.describe(json1);
			assertTrue(false);
		}catch (CycleReferenceException e) {
			log("{}",e.getMessage());
			assertTrue(true);			
		}
	}
	@Test
	public void test15List() {
		try {
			JSONObject json1 = new JSONObject().fluentPut("props", new JSONObject().fluentPut("p2", new JSONObject()));
			PublicFieldBean bean1 = new PublicFieldBean("tom","guangzhou",23,null,null);
			PublicFieldBean bean2 = new PublicFieldBean("jerry","beijing",33,null,null);
			BEAN_SUPPORT.setProperty(json1, "props.p2.p3", Lists.newArrayList(bean1,bean2));
			Map<String, Object> desc = BEAN_SUPPORT.describe(json1);
			log("{}",JSON.toJSONString(desc,true));
			assertTrue(bean2==BEAN_SUPPORT.getProperty(json1, "props.p2.p3.[1]"));
		}catch (CycleReferenceException e) {
			log("{}",e.getMessage());
		}
	}
	@Test
	public void test16Array() {
		try {
			JSONObject json1 = new JSONObject().fluentPut("props", new JSONObject().fluentPut("p2", new JSONObject()));
			PublicFieldBean bean1 = new PublicFieldBean("tom","guangzhou",23,null,null);
			PublicFieldBean bean2 = new PublicFieldBean("jerry","beijing",33,null,null);
			BEAN_SUPPORT.setProperty(json1, "props.p2.p3", new Object[] {bean1,bean2});
			Map<String, Object> desc = BEAN_SUPPORT.describe(json1);
			log("{}",JSON.toJSONString(desc,true));
			assertTrue(bean2==BEAN_SUPPORT.getProperty(json1, "props.p2.p3.[1]"));
		}catch (CycleReferenceException e) {
			log("{}",e.getMessage());
		}
	}
	@Test
	public void test17Set() {
		try {
			JSONObject json1 = new JSONObject().fluentPut("props", new JSONObject().fluentPut("p2", new JSONObject()));
			BEAN_SUPPORT.setProperty(json1, "props.p2.p3", Sets.newHashSet(null,2,3));
			Map<String, Object> desc = BEAN_SUPPORT.describe(json1);
			log("{}",JSON.toJSONString(desc,SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue));
			
		}catch (CycleReferenceException e) {
			log("{}",e.getMessage());
		}
	}
	@Test
	public void test18ArrayCycle() {
		try {
			JSONObject json1 = new JSONObject().fluentPut("props", new JSONObject().fluentPut("p2", new JSONObject()));
			PublicFieldBean bean1 = new PublicFieldBean("jerry","beijing",33,null,null);
			BEAN_SUPPORT.setProperty(json1, "props.p2.p3", new Object[] {bean1,json1});
			BEAN_SUPPORT.describe(json1,true);
			assertTrue(false);
		}catch (CycleReferenceException e) {
			log("CycleReferenceException:{}",e.getMessage());
			assertTrue(true);
		}
	}
	@Test
	public void test19ArrayBean() {
		try {
			JSONObject json1 = new JSONObject().fluentPut("props", new JSONObject().fluentPut("p2", new JSONObject()));
			PublicFieldBean bean1 = new PublicFieldBean("jerry","beijing",33,null,null);
			Object value=BEAN_SUPPORT.getProperty(new Object[] {bean1,json1}, "[1]");
			Map<String, Object> desc = BEAN_SUPPORT.describe(value);
			log("{}",JSON.toJSONString(desc,SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue));
			assertTrue(json1 == value);
		}catch (Exception e) {
			e.printStackTrace();
			assertTrue(false);
		}
	}
	@Test
	public void test20HasCycleReference() {
		try {
			JSONObject json1 = new JSONObject().fluentPut("props", new JSONObject().fluentPut("p2", new JSONObject()));
			BEAN_SUPPORT.setProperty(json1, "props.p2.p3", new Object[] {json1});
			assertTrue(BEAN_SUPPORT.hasCycleReference(json1));
			log("hasCycleReference");
		}catch (CycleReferenceException e) {
			log("CycleReferenceException:{}",e.getMessage());
			assertTrue(false);
		}
	}
	@Test
	public void test21CheckCycleReference() {
		try {
			JSONObject json1 = new JSONObject().fluentPut("props", new JSONObject().fluentPut("p2", new JSONObject()));
			BEAN_SUPPORT.setProperty(json1, "props.p2.p3", new Object[] {json1});
			BEAN_SUPPORT.checkCycleReference(json1);
			assertTrue("hasCycleReference",false);
		}catch (CycleReferenceException e) {
			log("CycleReferenceException:{}",e.getMessage());
			assertTrue(true);
		}
	}
}
